<script setup lang="ts">
import { animations, handleEnd, performTransfer } from '@formkit/drag-and-drop'
import { dragAndDrop } from '@formkit/drag-and-drop/vue'
import { VForm } from 'vuetify/components/VForm'
import type { AddNewKanbanItem, EditKanbanItem, KanbanData, KanbanState, RenameKanbanBoard } from '@db/apps/kanban/types'
import KanbanCard from '@/views/apps/kanban/KanbanCard.vue'

const props = defineProps<{
  kanbanIds: number[]
  groupName: string
  boardName: string
  boardId: number
  kanbanData: KanbanData
}>()

const emit = defineEmits<{
  (e: 'renameBoard', value: RenameKanbanBoard): void
  (e: 'deleteBoard', value: number): void
  (e: 'addNewItem', value: AddNewKanbanItem): void
  (e: 'editItem', value: EditKanbanItem | undefined): void
  (e: 'updateItemsState', value: KanbanState): void
  (e: 'deleteItem', value: EditKanbanItem): void
}>()

const refKanbanBoard = ref<HTMLElement>()
const localBoardName = ref(props.boardName)

const localIds = ref<number[]>(props.kanbanIds)

const isAddNewFormVisible = ref(false)
const isBoardNameEditing = ref(false)
const refForm = ref<VForm>()
const newTaskTitle = ref<string>('')
const refKanbanBoardTitle = ref<VForm>()

// 👉 required validator
const boardActions = [
  {
    title: 'Rename',
    prependIcon: 'tabler-pencil',
    onClick: () => { isBoardNameEditing.value = true },
  },
  {
    title: 'Delete',
    prependIcon: 'tabler-trash',
    onClick: () => (emit('deleteBoard', props.boardId)),
  },
]

// 👉 emit rename board event
const renameBoard = () => {
  refKanbanBoardTitle.value?.validate().then(valid => {
    if (valid.valid) {
      emit('renameBoard', {
        oldName: props.boardName,
        newName: localBoardName.value,
        boardId: props.boardId,
      })
      isBoardNameEditing.value = false
    }
  })
}

// 👉 emit add new item event
const addNewItem = () => {
  refForm.value?.validate().then(valid => {
    if (valid.valid) {
      emit('addNewItem', { itemTitle: newTaskTitle.value, boardName: props.boardName, boardId: props.boardId })
      isAddNewFormVisible.value = false
      newTaskTitle.value = ''
    }
  })
}

// 👉 initialize draggable
dragAndDrop({
  parent: refKanbanBoard,
  values: localIds,
  group: props.groupName,
  draggable: child => child.classList.contains('kanban-card'),
  plugins: [animations()],
  performTransfer: (state, data) => {
    performTransfer(state, data)

    // 👉 update items state after transfer perform
    emit('updateItemsState', { boardId: props.boardId, ids: localIds.value })
  },
  handleEnd: data => {
    handleEnd(data)

    // 👉 update items state after sorting perform
    emit('updateItemsState', { boardId: props.boardId, ids: localIds.value })
  },
})

// 👉 watch kanbanIds its is useful when you add new task
watch(() => props, () => {
  localIds.value = props.kanbanIds
}, { immediate: true, deep: true })

// 👉 resolve item using id
const resolveItemUsingId = (id: number) => props.kanbanData.items.find(item => item.id === id)

const deleteItem = (item: EditKanbanItem) => {
  emit('deleteItem', item)
}

// 👉 reset add new item form when esc or close
const hideAddNewForm = () => {
  isAddNewFormVisible.value = false
  refForm.value?.reset()
}

// close add new item form when you loose focus from the form
onClickOutside(refForm, hideAddNewForm)

// close board name form when you loose focus from the form
onClickOutside(refKanbanBoardTitle, () => {
  isBoardNameEditing.value = false
})

// 👉 reset board rename form when esc or close
const hideResetBoardNameForm = () => {
  isBoardNameEditing.value = false
  localBoardName.value = props.boardName
}

// 👉 submit form on enter and new line on shift-enter
const handleEnterKeydown = (event: { key: string; shiftKey: any }) => {
  if (event.key === 'Enter' && !event.shiftKey)
    addNewItem()
}
</script>

<template>
  <div class="kanban-board">
    <!-- 👉 board heading and title -->
    <div class="kanban-board-header pb-4">
      <VForm
        v-if="isBoardNameEditing"
        ref="refKanbanBoardTitle"
        @submit.prevent="renameBoard"
      >
        <VTextField
          v-model="localBoardName"
          autofocus
          variant="underlined"
          :rules="[requiredValidator]"
          hide-details
          class="border-0"
          @keydown.esc="hideResetBoardNameForm"
        >
          <template #append-inner>
            <VIcon
              size="20"
              color="success"
              icon="tabler-check"
              class="me-1"
              @click="renameBoard"
            />

            <VIcon
              size="20"
              color="error"
              icon="tabler-x"
              @click="hideResetBoardNameForm"
            />
          </template>
        </VTextField>
      </VForm>

      <div
        v-else
        class="d-flex align-center justify-space-between "
      >
        <h4 class="text-lg font-weight-medium text-truncate">
          {{ boardName }}
        </h4>

        <div class="d-flex align-center">
          <VIcon
            class="drag-handler"
            size="20"
            icon="tabler-arrows-move"
          />

          <MoreBtn
            size="28"
            icon-size="20"
            class="text-high-emphasis"
            :menu-list="boardActions"
            item-props
          />
        </div>
      </div>
    </div>

    <!-- 👉 draggable task start here -->
    <div
      v-if="localIds"
      ref="refKanbanBoard"
      class="kanban-board-drop-zone rounded d-flex flex-column gap-4"
      :class="localIds.length ? 'mb-4' : ''"
    >
      <template
        v-for="id in localIds"
        :key="id"
      >
        <KanbanCard
          :item="resolveItemUsingId(id)"
          :board-id="props.boardId"
          :board-name="props.boardName"
          @delete-kanban-item="deleteItem"
          @click="emit('editItem', { item: resolveItemUsingId(id), boardId: props.boardId, boardName: props.boardName })"
        />
      </template>

      <!-- 👉 Add new Form -->
      <div class="add-new-form">
        <h6
          class="text-base font-weight-regular cursor-pointer ms-4"
          @click="isAddNewFormVisible = !isAddNewFormVisible"
        >
          <VIcon
            size="15"
            icon="tabler-plus"
          /> Add New Item
        </h6>

        <VForm
          v-if="isAddNewFormVisible"
          ref="refForm"
          class="mt-4"
          validate-on="submit"
          @submit.prevent="addNewItem"
        >
          <div class="mb-4">
            <VTextarea
              v-model="newTaskTitle"
              :rules="[requiredValidator]"
              placeholder="Add Content"
              autofocus
              rows="2"
              @keydown.enter="handleEnterKeydown"
              @keydown.esc="hideAddNewForm"
            />
          </div>
          <div class="d-flex gap-4 flex-wrap">
            <VBtn
              size="small"
              type="submit"
            >
              Add
            </VBtn>
            <VBtn
              size="small"
              variant="tonal"
              color="secondary"
              @click="hideAddNewForm"
            >
              Cancel
            </VBtn>
          </div>
        </VForm>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.kanban-board-header {
  .drag-handler {
    cursor: grab;
    opacity: 0;

    &:active {
      cursor: grabbing;
    }
  }

  &:hover {
    .drag-handler {
      opacity: 1;
    }
  }
}
</style>
